#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>     /* IPV4 地址家族 */
#include <arpa/inet.h>      /* inet_pton */
#include <stdlib.h>
#include <unistd.h>
#include "datarcver.h"
#include "debug.h"

/**
 * NOTE: 本例创建一个socket连接,并初始化一个JSON接收器接受数据并打印
 * 
 * */

#define BUFLEN      20 * 1024

typedef struct ProcessArg
{
    const char*     ip;
    int             port;
}ProcessArg_t;

static DataReceiver_t* JSONRecverExampleInit(void);
static int Connect(const char* serverip, const uint16_t port);
void main(void)
{
    int cfd;
    int readlen;
    ProcessArg_t parg = {.ip = "192.168.1.25", .port = 6000};
    DataReceiver_t* jsonrcver = JSONRecverExampleInit();
    DataMan_t* dataman = jsonrcver->select;

    cfd = Connect(parg.ip, parg.port);

    while (1) {
        readlen = read(cfd, dataman->base + dataman->readlen, 
                                BUFLEN - dataman->readlen);
        if (readlen > 0) {
            dataman->readlen += readlen;
            jsonrcver->mo.bytescnt += dataman->readlen;

            jsonrcver->PackParser(jsonrcver, &parg);

            printf("-------------------------- : %d Datacnt : %ld Packcnt : %ld"
                " Errcnt : %ld\n", 
                dataman->readlen, jsonrcver->mo.bytescnt, 
                jsonrcver->mo.packcnt, jsonrcver->mo.errcnt);
        }
    }
    close(cfd);
}


/** ****************************************************************************
 * Use For     ---- JSON数据处理 
 * */
static void JSONRecver_PackProcessor(struct DataReceiver* this, ProcessArg_t* arg)
{
    if (this->packtype != PackType_Json) {
        DebugE("Error : packtype err, '%d' is not a valid type\n", 
                        this->packtype);
        return;
    }

    DebugLB("%s:%d JSON: %s\n", arg->ip, arg->port, this->select->base);
}

/** ****************************************************************************
 * Use For     ---- 错误数据处理
 * */
static void JSONRecver_DumpProcessor(struct DataReceiver* this, ProcessArg_t* arg)
{
    DebugE("%s:%d Error: %s\n", arg->ip, arg->port, this->dumppool);
}



/** ****************************************************************************
 * Use For     ---- 初始化 JSON 接收器, 并初始化垃圾处理器
 * */
static DataReceiver_t* JSONRecverExampleInit(void)
{
    static DataReceiver_t JSON;
    JSONRecverInit(&JSON, BUFLEN, 
        (void (*)(struct DataReceiver* , void* ))JSONRecver_PackProcessor);
    
    DumppoolProcessorInit(&JSON, 20 * 1024, 
        (void (*)(struct DataReceiver* , void* ))JSONRecver_DumpProcessor);

    return &JSON;
}





/* ****************************************************************************
 * Use For     ---- 连接指定服务
 * */
static int Connect(const char* serverip, const uint16_t port)
{
    struct sockaddr_in serv;
    /* 指定为IPv4地址 */
    serv.sin_family = AF_INET;
    /* 端口，主机序转网络序 */
    serv.sin_port = htons(port);
    /* 转换ip字符串为ipv4地址结构 */
    inet_pton(AF_INET, serverip, &serv.sin_addr);

    /* 创建socket，返回文件描述符 */
    int newfd = socket(AF_INET, SOCK_STREAM, 0);
    if (newfd == -1){
        DebugE("Get socket fd err\n");
        exit(-1);
    }

    /* 使用fd发起连接 */
    if (connect(newfd, (struct sockaddr*)&serv, sizeof(serv)) == -1) {
        DebugE("Error : connect to %s:%d failed\n", serverip, port);
        exit(-1);
    }
    return newfd;
}

